package com.ly.heart.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.common.PageParam;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.*;
import com.ly.heart.domain.dto.StartProcessDto;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.heart.mapper.KingSaleRefundMapper;
import com.ly.heart.service.*;
import com.ly.heart.util.ChineseToPinyin;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.system.service.ISysDeptService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


import javax.annotation.Resource;

/**
 * 金蝶-销售退货单Service业务层处理
 *
 * @author wutao
 * @date 2024-07-14
 */
@Service
public class KingSaleRefundServiceImpl extends ServiceImpl<KingSaleRefundMapper, KingSaleRefundEntity> implements IKingSaleRefundService {

    @Resource
    private KingSaleRefundMapper kingSaleRefundEntityMapper;
    @Resource
    private ISysDeptService sysDeptService;
    @Resource
    private IKingInventoryService kingInventoryService;
    @Resource
    private IKingInventoryMaterialService kingInventoryMaterialService;
    @Resource
    private IKingSaleRefundDetailService kingSaleRefundDetailService;
    @Resource
    private IKingSaleRefundDetailMaterialService kingSaleRefundDetailMaterialService;
    @Resource
    private IActModelService actModelService;
    @Resource
    private IKingRealInventoryService kingRealInventoryEntityService;
    @Resource
    private IActTaskCommentService iActTaskCommentService;


    //    @Override
//    @Transactional(rollbackFor = Exception.class)
    private AjaxResult saveKingSaleRefund ( KingSaleRefundEntity kingSaleRefundEntity ) {
        if ( StringUtils.isBlank ( kingSaleRefundEntity.getId () ) ) {
            return AjaxResult.error ( "请先暂存该单据！" );
        }
        if ( Objects.isNull ( kingSaleRefundEntity.getModelId () ) ) {
            return AjaxResult.error ( "审批流程modelId不能为空！" );
        }
        if ( CollectionUtils.isEmpty ( kingSaleRefundEntity.getKingSaleRefundDetailEntityList () ) ) {
            return AjaxResult.error ( "退货销售物品不能为空" );
        }
        List<KingSaleRefundDetailEntity> kingSaleRefundDetailEntityList = kingSaleRefundEntity.getKingSaleRefundDetailEntityList ();
        List<String> stringList = kingSaleRefundDetailEntityList.parallelStream ()
                .filter ( Objects :: nonNull )
                .map ( KingSaleRefundDetailEntity :: getRelationId )
                .distinct()
                .collect ( Collectors.toList () );
        List<KingInventoryEntity> list = kingInventoryService.list ( new LambdaQueryWrapper<KingInventoryEntity> ().in ( KingInventoryEntity :: getId, stringList ) );
        Set<String> customerList = list.stream ()
                .map ( KingInventoryEntity :: getCustomerId ) // 提取每个Customer对象的customerId属性
                .collect ( Collectors.toSet () );
        if ( customerList.size () > 1 ) {
            return AjaxResult.error ( "退货销售物品客户不一致" );
        }
        Set<String> settlementCurrencyList = list.stream ().map ( KingInventoryEntity :: getSettlementCurrency ).collect ( Collectors.toSet () );
        if ( settlementCurrencyList.size () > 1 ) {
            return AjaxResult.error ( "退货销售物品结算货币不一致" );
        }
        //校验销售退货单明细
        checkSaleRefundDetailEntityList ( kingSaleRefundDetailEntityList );
        //保存物料明细以及物料分录信息
        saveMaterialAndDetail ( kingSaleRefundEntity, kingSaleRefundDetailEntityList, "提交" );
        //启动审批流程
        StartProcessDto startDto = new StartProcessDto ().setBusinessId ( kingSaleRefundEntity.getId () ).setBusinessType ( kingSaleRefundEntity.getBusinessType () ).setModelId ( kingSaleRefundEntity.getModelId () );
        startDto.setBusinessName ( "销售退货单_".concat ( kingSaleRefundEntity.getRefundCode () ) );
        String instanceId = actModelService.startProcess ( startDto );
        kingSaleRefundEntity.setInstanceId ( instanceId );
        kingSaleRefundEntity.setState ( ConstUtil.STATE_IN_PROCESS );
        boolean updated = this.updateById ( kingSaleRefundEntity );
        if ( ! updated ) {
            return AjaxResult.error ( "销售退货单提交失败" );
        } else {
            return AjaxResult.success ( "销售退货单提交成功" );
        }
    }

    /**
     * 销售退回列表新接口
     *
     * @param kingSaleRefundEntity
     * @return
     */
    @Override
    public AjaxResult queryList ( KingSaleRefundEntity kingSaleRefundEntity ) {
        kingSaleRefundEntity.setPage ( ( kingSaleRefundEntity.getPage () - 1 ) * kingSaleRefundEntity.getLimit () );
        List<KingSaleRefundEntity> kingSaleRefundEntities = kingSaleRefundEntityMapper.queryList ( kingSaleRefundEntity );
        kingSaleRefundEntities.forEach ( refund -> {
            //处理最后一个审批人
            ActTaskCommentEntity actTaskCommentEntity = iActTaskCommentService.queryLastComment ( refund.getInstanceId () );
            if ( actTaskCommentEntity != null ) {
                refund.setApprovedUser ( actTaskCommentEntity.getApprovedUser () );
                refund.setApprovedRemark ( actTaskCommentEntity.getRemark () );
            }
            //任务信息
            ActCurrentTaskVo currentTaskVo = actModelService.getCurrentTaskByInstanceId ( refund.getInstanceId () );
            Optional.ofNullable ( currentTaskVo ).ifPresent ( currentTask -> {
                refund.setCurrentTask ( currentTask );
            } );
        } );
        Integer integer = kingSaleRefundEntityMapper.queryCount ( kingSaleRefundEntity );
        PageParam p = new PageParam ();
        p.setRecords ( kingSaleRefundEntities ).setTotal ( integer );
        return AjaxResult.success ( p );
    }

    @Override
    public AjaxResult draft ( KingSaleRefundEntity kingSaleRefundEntity ) {
        boolean saveFlag = false;
        if ( StringUtils.isEmpty ( kingSaleRefundEntity.getId () ) ) {
            String saleRefundId = SnowflakeIdWorker.getInstance ().nextStringId ();
            Date nowDate = DateUtils.getNowDate ();
            String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
            kingSaleRefundEntity.setId ( saleRefundId );
            kingSaleRefundEntity.setCreateBy ( userId );
            kingSaleRefundEntity.setCreateTime ( nowDate );
            if ( StringUtils.isEmpty ( kingSaleRefundEntity.getRefundCode () ) ) {
                String companyId = CurrentUserUtil.getCompanyId ();
                SysDept sysDept = sysDeptService.getById ( companyId );
                int count = this.count ();
                String countStr = String.format ( "%06d", count );
                String firstLetter = ChineseToPinyin.getFirstLetter ( sysDept.getDeptName () );
                String refundCode = firstLetter.concat ( "_XSTH_" ).concat ( countStr );
                kingSaleRefundEntity.setRefundCode ( refundCode );
            }
            if ( ! CollectionUtils.isEmpty ( kingSaleRefundEntity.getKingSaleRefundDetailEntityList () ) ) {
                //保存物料明细以及物料分录信息
                saveMaterialAndDetail ( kingSaleRefundEntity, kingSaleRefundEntity.getKingSaleRefundDetailEntityList (), "暂存" );
            }
            kingSaleRefundEntity.setState ( ConstUtil.STATE_IN_DRAFT );
            saveFlag = this.save ( kingSaleRefundEntity );
        } else {
            if ( ! CollectionUtils.isEmpty ( kingSaleRefundEntity.getKingSaleRefundDetailEntityList () ) ) {
                //保存物料明细以及物料分录信息
                saveMaterialAndDetail ( kingSaleRefundEntity, kingSaleRefundEntity.getKingSaleRefundDetailEntityList (), "提交" );
            }
            saveFlag = this.updateById ( kingSaleRefundEntity );
        }

        if ( saveFlag ) {
            return AjaxResult.success ( "销售退货单暂存成功", kingSaleRefundEntity.getId () );
        } else {
            return AjaxResult.error ( "销售退货单暂存失败" );
        }
    }

    @Override
    @Transactional ( rollbackFor = Exception.class )
    public AjaxResult submit ( KingSaleRefundEntity kingSaleRefundEntity ) {
        return this.saveKingSaleRefund ( kingSaleRefundEntity );
    }

    /**
     * 审批销售退货单
     *
     * @param kingSaleRefundEntity
     * @return
     */
    @Override
    @Transactional ( rollbackFor = Exception.class )
    public boolean approvedSaleKingSaleRefund ( KingSaleRefundEntity kingSaleRefundEntity ) {
        List<KingSaleRefundDetailEntity> refundDetailEntities = kingSaleRefundDetailService.list ( new LambdaQueryWrapper<KingSaleRefundDetailEntity> ()
                .eq ( KingSaleRefundDetailEntity :: getSaleRefundId, kingSaleRefundEntity.getId () ) );
        refundDetailEntities.forEach ( refundDetail -> {
            if ( ! refundDetail.getRefundType ().equals ( ConstUtil.SALE_REFUND_TYPE_ONLY_REFUND ) ) {
                KingRealInventoryEntity realInventoryEntity = kingRealInventoryEntityService.getOne ( new LambdaQueryWrapper<KingRealInventoryEntity> ()
                        .eq ( KingRealInventoryEntity :: getMaterialCode, refundDetail.getMaterialCode () )
                        .eq ( KingRealInventoryEntity :: getWarehouseCode, refundDetail.getWarehouseCode () )
                        .eq ( KingRealInventoryEntity :: getWarehousePosition, refundDetail.getWarehousePosition () )
                );
                if ( Objects.isNull ( realInventoryEntity ) ) {//此物料是第一次退回添加库存
                    KingRealInventoryEntity kingRealInventoryEntity = new KingRealInventoryEntity ();
                    kingRealInventoryEntity.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                    kingRealInventoryEntity.setMaterialCode ( refundDetail.getMaterialCode () );
                    kingRealInventoryEntity.setWarehouseCode ( refundDetail.getWarehouseCode () );
                    kingRealInventoryEntity.setWarehousePosition ( refundDetail.getWarehousePosition () );
                    kingRealInventoryEntity.setInventoryNum ( refundDetail.getRefundNum () );
                    kingRealInventoryEntity.setCreateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
                    kingRealInventoryEntityService.save ( kingRealInventoryEntity );

                } else {//修改库存
                    String surplusInventoryNum = CommonUtil.subStr ( realInventoryEntity.getInventoryNum (), refundDetail.getRefundNum (), 2 );
                    realInventoryEntity.setInventoryNum ( surplusInventoryNum );
                    realInventoryEntity.setUpdateTime ( DateUtils.getNowDate () );
                    realInventoryEntity.setUpdateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
                    kingRealInventoryEntityService.updateById ( realInventoryEntity );
                }
            }
        } );
        return true;
    }

    /**
     * 校验销售退货单明细
     *
     * @param kingSaleRefundDetailEntityList
     */
    private void checkSaleRefundDetailEntityList ( List<KingSaleRefundDetailEntity> kingSaleRefundDetailEntityList ) {
        for ( KingSaleRefundDetailEntity material : kingSaleRefundDetailEntityList ) {
            KingInventoryMaterialEntity outInventoryMaterialDetailOne = kingInventoryMaterialService.getById ( material.getSourceMaterialDetailId () );

            //计算总金额
            BigDecimal totalMoneyAmount = new BigDecimal ( outInventoryMaterialDetailOne.getMoneyAmount () );
            //出库的总数
            double inventoryNum = Double.parseDouble ( outInventoryMaterialDetailOne.getReceiptsNum () );

            List<KingSaleRefundDetailEntity> refundDetailEntities = kingSaleRefundDetailService.list ( new LambdaQueryWrapper<KingSaleRefundDetailEntity> ()
                    .eq ( KingSaleRefundDetailEntity :: getSourceMaterialDetailId, material.getSourceMaterialDetailId () )
                    .ne ( KingSaleRefundDetailEntity :: getId, material.getId () )
            );

            BigDecimal reduced = refundDetailEntities.stream ().map ( KingSaleRefundDetailEntity :: getRefundNum )
                    .filter ( m -> m != null && ! m.isEmpty () )
                    .map ( BigDecimal :: new )
                    .reduce ( BigDecimal.ZERO, BigDecimal :: add );
//            //退货，仅退款不退货总合
//            BigDecimal refundNum =refundDetailEntities.stream()
//                    .filter(kingSaleRefundDetailEntity ->
//                            !ConstUtil.SALE_REFUND_TYPE_REFUND_AND_REPLACE.equals(kingSaleRefundDetailEntity.getRefundType()))
//                    .map(KingSaleRefundDetailEntity::getRefundNum)
//                    .filter(m->m!=null && !m.isEmpty())
//                    .map(BigDecimal::new)
//                    .reduce(BigDecimal.ZERO, BigDecimal::add);
//            //退货补货数量
//            BigDecimal decimal = refundDetailEntities.stream().filter(king -> ConstUtil.SALE_REFUND_TYPE_REFUND_AND_REPLACE.equals(king.getRefundType()))
//                    .map(KingSaleRefundDetailEntity::getRefundNum)
//                    .filter(m -> m != null && !m.isEmpty())
//                    .map(BigDecimal::new)
//                    .reduce(BigDecimal.ZERO, BigDecimal::add);
//            BigDecimal surplusNum = new BigDecimal(inventoryNum).subtract(refundNum).add(decimal);
            BigDecimal surplusRefundNum = new BigDecimal ( inventoryNum ).subtract ( reduced );
            if ( surplusRefundNum.compareTo ( new BigDecimal ( material.getRefundNum () ) ) < 0 ) {
                throw new RuntimeException ( "退货数量不能大于剩余退货数量" );
            }

            if ( inventoryNum < Integer.valueOf ( material.getRefundNum () ) ) {
                throw new RuntimeException ( "退货数量不能大于出库数量" );
            }
            if ( material.getRefundType ().equals ( ConstUtil.SALE_REFUND_TYPE_ONLY_REFUND ) ) {
                BigDecimal surplusRefundPrice = refundDetailEntities.stream ()
                        .filter ( king -> king.getRefundType ().equals ( ConstUtil.SALE_REFUND_TYPE_ONLY_REFUND ) )
                        .map ( KingSaleRefundDetailEntity :: getTaxPrice )
                        .filter ( m -> m != null && ! m.isEmpty () )
                        .map ( BigDecimal :: new )
                        .reduce ( BigDecimal.ZERO, BigDecimal :: add );
                if ( totalMoneyAmount.compareTo ( surplusRefundPrice ) < 0 ) {
                    throw new RuntimeException ( "退货金额不能大于出库剩余的可退货的金额" );
                }
            }
            if ( surplusRefundNum.compareTo ( new BigDecimal ( material.getRefundNum () ) ) == 0 ) {
                KingInventoryMaterialEntity kingInventoryMaterialDetail = kingInventoryMaterialService.getById ( material.getSourceMaterialDetailId () );
//                KingInventoryMaterialDetailEntity kingInventoryMaterialDetail = kingInventoryMaterialDetailService.getOne ( new QueryWrapper<KingInventoryMaterialDetailEntity> ().eq ( "inventory_material_id", outInventoryMaterialDetailOne.getId () ) );
                String inventoryTotalTaxPrice = kingInventoryMaterialDetail.getTotalTaxPrice ();
                //该物料明细已经形成销售退料单的价税合计
                BigDecimal saleRefundToatlTaxPrice = refundDetailEntities.stream ().filter ( Objects :: nonNull ).map ( materialDetail -> new BigDecimal ( materialDetail.getTotalTaxPrice () ) ).reduce ( BigDecimal.ZERO, BigDecimal :: add );
                //计算剩余的价税合计(该物料明细的价税合计 ➖ 已经形成销售出库单的价税合计)
                BigDecimal surplusTotalTaxPrice = new BigDecimal ( inventoryTotalTaxPrice ).subtract ( saleRefundToatlTaxPrice );
                //计算单价(剩余的价税合计 / 此次数量)
                BigDecimal price = surplusTotalTaxPrice.divide ( new BigDecimal ( material.getRefundNum () ), BigDecimal.ROUND_HALF_UP );
                //将值赋值给原字段
                material.setPrice ( String.valueOf ( price ) );
                material.setTotalTaxPrice ( String.valueOf ( surplusTotalTaxPrice ) );
            }
        }
    }

    /**
     * 保存物料明细以及物料分录信息
     *
     * @param kingSaleRefundEntity
     * @param kingSaleRefundDetailEntityList
     */
    private void saveMaterialAndDetail ( KingSaleRefundEntity kingSaleRefundEntity, List<KingSaleRefundDetailEntity> kingSaleRefundDetailEntityList, String message ) {
        if ( "提交".equals ( message ) ) {
            kingSaleRefundDetailService.remove ( new LambdaQueryWrapper<> ( KingSaleRefundDetailEntity.class ).eq ( KingSaleRefundDetailEntity :: getRelationId, kingSaleRefundEntity.getId () ) );
        }
        for ( KingSaleRefundDetailEntity material : kingSaleRefundDetailEntityList ) {
            String detailId = SnowflakeIdWorker.getInstance ().nextStringId ();
            material.setId ( detailId );
            material.setRelationId ( kingSaleRefundEntity.getId () );
            material.setCreateBy ( kingSaleRefundEntity.getCreateBy () );
            material.setCreateTime ( kingSaleRefundEntity.getCreateTime () );
            boolean save = kingSaleRefundDetailService.save ( material );
            if ( save ) {
                KingSaleRefundDetailMaterialEntity kingSaleRefundDetailMaterialEntity = material.getKingSaleRefundDetailMaterialEntity ();
                Optional.ofNullable ( kingSaleRefundDetailMaterialEntity ).ifPresent ( materialDetail -> {
                    String id = SnowflakeIdWorker.getInstance ().nextStringId ();
                    kingSaleRefundDetailMaterialEntity.setId ( id );
                    kingSaleRefundDetailMaterialEntity.setSaleRefundId ( kingSaleRefundEntity.getId () );
                    kingSaleRefundDetailMaterialEntity.setSaleRefundMaterialId ( detailId );
                    kingSaleRefundDetailMaterialEntity.setCreateBy ( kingSaleRefundEntity.getCreateBy () );
                    kingSaleRefundDetailMaterialEntity.setCreateTime ( kingSaleRefundEntity.getCreateTime () );
                    boolean saved = kingSaleRefundDetailMaterialService.save ( kingSaleRefundDetailMaterialEntity );
                    if ( ! saved ) {
                        throw new RuntimeException ( "金蝶-销售退货单明细关联金蝶-销售退货单明细关联失败" );
                    }
                } );
            } else {
                throw new RuntimeException ( "金蝶-销售退货单明细" + message + "失败" );
            }
        }
    }

    /**
     * 查询金蝶-销售退货单
     *
     * @param id 金蝶-销售退货单ID
     * @return 金蝶-销售退货单
     */
    @Override
    public KingSaleRefundEntity selectKingSaleRefundEntityById ( String id ) {
        KingSaleRefundEntity kingSaleRefundEntity = kingSaleRefundEntityMapper.selectKingSaleRefundEntityById ( id );
        KingSaleRefundDetailEntity saleRefundDetailEntity = new KingSaleRefundDetailEntity ();
        saleRefundDetailEntity.setRelationId ( id );
        List<KingSaleRefundDetailEntity> kingSaleRefundDetailEntities = kingSaleRefundDetailService.selectKingSaleRefundDetailEntityList ( saleRefundDetailEntity );
        kingSaleRefundEntity.setKingSaleRefundDetailEntityList ( kingSaleRefundDetailEntities );
        return kingSaleRefundEntity;
    }

    /**
     * 查询金蝶-销售退货单列表
     *
     * @param kingSaleRefundEntity 金蝶-销售退货单
     * @return 金蝶-销售退货单
     */
    @Override
    public List<KingSaleRefundEntity> selectKingSaleRefundEntityList ( KingSaleRefundEntity kingSaleRefundEntity ) {
        return kingSaleRefundEntityMapper.selectKingSaleRefundEntityList ( kingSaleRefundEntity );
    }

    /**
     * 新增金蝶-销售退货单
     *
     * @param kingSaleRefundEntity 金蝶-销售退货单
     * @return 结果
     */
    @Override
    public int insertKingSaleRefundEntity ( KingSaleRefundEntity kingSaleRefundEntity ) {
        kingSaleRefundEntity.setCreateTime ( DateUtils.getNowDate () );
        return kingSaleRefundEntityMapper.insertKingSaleRefundEntity ( kingSaleRefundEntity );
    }

    /**
     * 修改金蝶-销售退货单
     *
     * @param kingSaleRefundEntity 金蝶-销售退货单
     * @return 结果
     */
    @Override
    public int updateKingSaleRefundEntity ( KingSaleRefundEntity kingSaleRefundEntity ) {
        kingSaleRefundEntity.setUpdateTime ( DateUtils.getNowDate () );
        return kingSaleRefundEntityMapper.updateKingSaleRefundEntity ( kingSaleRefundEntity );
    }

    /**
     * 批量删除金蝶-销售退货单
     *
     * @param ids 需要删除的金蝶-销售退货单ID
     * @return 结果
     */
    @Override
    public int deleteKingSaleRefundEntityByIds ( String[] ids ) {
        return kingSaleRefundEntityMapper.deleteKingSaleRefundEntityByIds ( ids );
    }

    /**
     * 删除金蝶-销售退货单信息
     *
     * @param id 金蝶-销售退货单ID
     * @return 结果
     */
    @Override
    public int deleteKingSaleRefundEntityById ( String id ) {
        return kingSaleRefundEntityMapper.deleteKingSaleRefundEntityById ( id );
    }

    @Override
    public KingSaleRefundEntity getKingById ( String id ) {
        KingSaleRefundEntity kingById = kingSaleRefundEntityMapper.getKingById ( id );
        return kingById;
    }
}
